﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using AIStudio.Wpf.DiagramApp.Models;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.Logical;
using AIStudio.Wpf.Logical.ViewModels;

namespace AIStudio.Wpf.DiagramApp.ViewModels
{
    public class LogicalViewModel : PageViewModel
    {
        public LogicalViewModel(string title, string status, DiagramType diagramType) : base(title, status, diagramType)
        {

        }
        public LogicalViewModel(string filename, DiagramDocument diagramDocument) : base(filename, diagramDocument)
        {
            _service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
        }

        protected override void InitDiagramViewModel()
        {
            base.InitDiagramViewModel();

            DiagramViewModel.DiagramOption.LayoutOption.ShowGrid = true;
            DiagramViewModel.DiagramOption.LayoutOption.GridCellSize = new Size(150, 100);
            DiagramViewModel.DiagramOption.LayoutOption.PageSizeOrientation = PageSizeOrientation.Horizontal;
            DiagramViewModel.DiagramOption.LayoutOption.CellHorizontalAlignment = CellHorizontalAlignment.Left;
            DiagramViewModel.DiagramOption.LayoutOption.CellVerticalAlignment = CellVerticalAlignment.None;

            DiagramViewModel.Items.CollectionChanged += Items_CollectionChanged;
            _service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
        }

        protected override void Init(bool initNew)
        {
            base.Init(initNew);

            TimerDesignerItemViewModel timer = new TimerDesignerItemViewModel() { Left = 28, Top = 28 };
            timer.Value = 1;
            DiagramViewModel.Add(timer);

            InputItemViewModel in1 = new InputItemViewModel() { Left = 28, Top = 110 };
            in1.LinkPoint = LogicalService.LinkPoint[0];
            DiagramViewModel.Add(in1);

            InputItemViewModel in2 = new InputItemViewModel() { Left = 28, Top = 300 };
            in2.LinkPoint = LogicalService.LinkPoint[1];
            DiagramViewModel.Add(in2);

            AddGateItemViewModel item1 = new AddGateItemViewModel() { Left = 178, Top = 160 };
            DiagramViewModel.Add(item1);

            ConstantDesignerItemViewModel constant = new ConstantDesignerItemViewModel() { Left = 178, Top = 300, Value = 10 };
            DiagramViewModel.Add(constant);

            GTGateItemViewModel gTGate = new GTGateItemViewModel() { Left = 328, Top = 110 };
            DiagramViewModel.Add(gTGate);

            InputItemViewModel in3 = new InputItemViewModel() { Left = 328, Top = 210 };
            in3.LinkPoint = LogicalService.LinkPoint[2];
            DiagramViewModel.Add(in3);

            InputItemViewModel in4 = new InputItemViewModel() { Left = 328, Top = 300 };
            in4.LinkPoint = LogicalService.LinkPoint[3];
            DiagramViewModel.Add(in4);

            SELGateItemViewModel sELGate = new SELGateItemViewModel() { Left = 478, Top = 160 };
            DiagramViewModel.Add(sELGate);

            OutputItemViewModel out1 = new OutputItemViewModel() { Left = 628, Top = 110 };
            out1.LinkPoint = LogicalService.LinkPoint[4];
            DiagramViewModel.Add(out1);

            ConnectionViewModel connector1 = new ConnectionViewModel(in1.Output[0], item1.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector1.ColorViewModel.FillColor.Color = Colors.Green;
            connector1.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector1);

            ConnectionViewModel connector2 = new ConnectionViewModel(in2.Output[0], item1.Input[1], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector2.ColorViewModel.FillColor.Color = Colors.Green;
            connector2.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector2);

            ConnectionViewModel connector3 = new ConnectionViewModel(item1.Output[0], gTGate.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector3.ColorViewModel.FillColor.Color = Colors.Green;
            connector3.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector3);

            ConnectionViewModel connector4 = new ConnectionViewModel(constant.Output[0], gTGate.Input[1], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector4.ColorViewModel.FillColor.Color = Colors.Green;
            connector4.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector4);

            ConnectionViewModel connector5 = new ConnectionViewModel(gTGate.Output[0], sELGate.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector5.ColorViewModel.FillColor.Color = Colors.Green;
            connector5.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector5);

            ConnectionViewModel connector6 = new ConnectionViewModel(in3.Output[0], sELGate.Input[1], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector6.ColorViewModel.FillColor.Color = Colors.Green;
            connector6.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector6);

            ConnectionViewModel connector7 = new ConnectionViewModel(in4.Output[0], sELGate.Input[2], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector7.ColorViewModel.FillColor.Color = Colors.Green;
            connector7.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector7);

            ConnectionViewModel connector8 = new ConnectionViewModel(sELGate.Output[0], out1.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode);
            connector8.ColorViewModel.FillColor.Color = Colors.Green;
            connector8.AnimationViewModel.Animation = LineAnimation.PathAnimation;
            DiagramViewModel.Add(connector8);
        }

        private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (var item in e.OldItems.OfType<TimerDesignerItemViewModel>())
                {
                    item.Do -= Do;
                }
            }
            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems.OfType<TimerDesignerItemViewModel>())
                {
                    item.Do += Do;
                }
            }

            RaisePropertyChanged("Items");
        }

        protected override bool AddVerify(SelectableDesignerItemViewModelBase arg)
        {
            if (base.AddVerify(arg) == false)
                return false;

            if (arg is ConnectionViewModel connector)
            {
                if (connector.IsFullConnection)
                {
                    if (DiagramViewModel.Items.OfType<ConnectionViewModel>().Any(p => p.SinkConnectorInfo == connector.SinkConnectorInfoFully))
                    {
                        return false;
                    }
                }
            }

            if (arg is TimerDesignerItemViewModel)
            {
                if (DiagramViewModel.Items.OfType<LogicalGateItemViewModelBase>().Any(p => p.LogicalType == LogicalType.Time))
                {
                    return false;
                }
            }

            return true;
        }

        private void Do()
        {
            Random rd = new Random();
            foreach (var link in LogicalService.LinkPoint)
            {
                link.Value = rd.NextDouble() * 10;
            }

            foreach (var item in DiagramViewModel.Items.OfType<LogicalGateItemViewModelBase>().OrderBy(p => p.OrderNumber))
            {
                item.Execute();
            }
        }
    }
}
